/*
 * Copyright 2013 Rodrigo Villablanca <rvillablanca@orangepeople.cl>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cl.rvillablanca.jpatch.gui;

import cl.rvillablanca.jpatch.core.Copier;
import cl.rvillablanca.jpatch.core.Differenciator;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;

/**
 * Gui of JPatch
 *
 * @author Rodrigo Villablanca <rvillablanca@orangepeople.cl>
 */
public class View extends JFrame implements PropertyChangeListener {

    private static final long serialVersionUID = 3596091821006665743L;
    private JFileChooser chooser = new JFileChooser();
    private Differenciator diff = new Differenciator();
    private Copier copier = new Copier();
    private SwingWorker<Void, Void> worker = null;
    private static final Logger LOGGER = Logger.getLogger(View.class.getName());

    private enum SearchType {

        BASE, WORKING, SAVE
    };

    public View() {
        initComponents();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        GridBagConstraints gridBagConstraints;
        JLabel baseLabel = new JLabel();
        baseText = new JTextField();
        baseButton = new JButton();
        JLabel workingLabel = new JLabel();
        workingText = new JTextField();
        workingButton = new JButton();
        generateButton = new JButton();
        saveLabel = new JLabel();
        saveText = new JTextField();
        saveButton = new JButton();
        progress = new JProgressBar();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setTitle("JPatch");
        setResizable(false);
        GridBagLayout layout = new GridBagLayout();
        layout.columnWidths = new int[] {0, 20, 0, 20, 0};
        layout.rowHeights = new int[] {0, 20, 0, 20, 0, 20, 0, 20, 0};
        getContentPane().setLayout(layout);

        baseLabel.setText("Base");
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = GridBagConstraints.LINE_START;
        getContentPane().add(baseLabel, gridBagConstraints);

        baseText.setEditable(false);
        baseText.setColumns(15);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        getContentPane().add(baseText, gridBagConstraints);

        baseButton.setText("Search");
        baseButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                baseButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        getContentPane().add(baseButton, gridBagConstraints);

        workingLabel.setText("Working");
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = GridBagConstraints.LINE_START;
        getContentPane().add(workingLabel, gridBagConstraints);

        workingText.setEditable(false);
        workingText.setColumns(15);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        getContentPane().add(workingText, gridBagConstraints);

        workingButton.setText("Search");
        workingButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                workingButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 2;
        getContentPane().add(workingButton, gridBagConstraints);

        generateButton.setText("Generate Path");
        generateButton.setEnabled(false);
        generateButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                generateButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.anchor = GridBagConstraints.LINE_START;
        getContentPane().add(generateButton, gridBagConstraints);

        saveLabel.setText("Save in");
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        getContentPane().add(saveLabel, gridBagConstraints);

        saveText.setEditable(false);
        saveText.setColumns(15);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 4;
        getContentPane().add(saveText, gridBagConstraints);

        saveButton.setText("Search");
        saveButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 4;
        getContentPane().add(saveButton, gridBagConstraints);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.gridwidth = 5;
        getContentPane().add(progress, gridBagConstraints);

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-391)/2, (screenSize.height-243)/2, 391, 243);
    }// </editor-fold>//GEN-END:initComponents

    private void baseButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_baseButtonActionPerformed
        searchDirectory(SearchType.BASE);
    }//GEN-LAST:event_baseButtonActionPerformed

    private void workingButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_workingButtonActionPerformed
        searchDirectory(SearchType.WORKING);
    }//GEN-LAST:event_workingButtonActionPerformed

    private void saveButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        searchDirectory(SearchType.SAVE);
    }//GEN-LAST:event_saveButtonActionPerformed

    private void generateButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_generateButtonActionPerformed
        worker = new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                saveButton.setEnabled(false);
                workingButton.setEnabled(false);
                baseButton.setEnabled(false);
                generateButton.setEnabled(false);
                progress.setIndeterminate(true);
                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                List<Path> pathList = diff.difference(workingText.getText(), baseText.getText());
                copier.setDestination(Paths.get(saveText.getText()));
                copier.setWorking(Paths.get(workingText.getText()));
                progress.setIndeterminate(false);
                progress.setValue(0);
                progress.setMinimum(0);
                progress.setMaximum(pathList.size());
                LOGGER.log(Level.CONFIG, "Maximun progress: {0}", pathList.size());
                int count = 0;
                for (Path p : pathList) {
                    count++;
                    copier.copyFile(p);
                    LOGGER.log(Level.CONFIG, "Current progress: {0}", count);
                    setProgress(count);
                }
                return null;
            }

            @Override
            protected void done() {
                Toolkit.getDefaultToolkit().beep();
                JOptionPane.showMessageDialog(View.this, "Patch has been generated");
                setCursor(null);
            }
        };
        worker.addPropertyChangeListener(this);
        worker.execute();
    }//GEN-LAST:event_generateButtonActionPerformed

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress".equals(evt.getPropertyName())) {
            Integer p = (Integer) evt.getNewValue();
            LOGGER.log(Level.CONFIG, "Setting progress bar value: {0}", p);
            progress.setValue(p);
        } else {
            LOGGER.log(Level.CONFIG, "Property type: {0}", evt.getPropertyName());
        }
    }

    private void searchDirectory(SearchType type) {
        switch (type) {
            case BASE:
                chooser.setDialogTitle("Base directory");
                break;
            case WORKING:
                chooser.setDialogTitle("Working directory");
                break;
            case SAVE:
                chooser.setDialogTitle("Save directory");
        }
        int value = chooser.showOpenDialog(this);
        if (value == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            switch (type) {
                case BASE:
                    baseText.setText(file.getAbsolutePath());
                    break;
                case WORKING:
                    workingText.setText(file.getAbsolutePath());
                    break;
                case SAVE:
                    saveText.setText(file.getAbsolutePath());
            }
        }
        checkGenerateButton();
    }

    private void checkGenerateButton() {
        generateButton.setEnabled(validPath(baseText.getText()) && validPath(workingText.getText()) && validPath(saveText.getText()));
    }

    private boolean validPath(String path) {
        return path != null && !"".equals(path);
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private JButton baseButton;
    private JTextField baseText;
    private JButton generateButton;
    private JProgressBar progress;
    private JButton saveButton;
    private JLabel saveLabel;
    private JTextField saveText;
    private JButton workingButton;
    private JTextField workingText;
    // End of variables declaration//GEN-END:variables
}
